import { OrgPageItem } from './../domain/models/orgPageItem';
import { IQueryObject } from 'tiny-entity2/queryObject';
import { PageTmpItem } from './../domain/models/pageTmpItem';
import { ApiDataContext } from "../domain/apiDataContext";
import { BaseService, QueryParamsBase } from "./baseService";
import { Page, PageType } from "../domain/models/page";
import { Transaction } from "tiny-entity2";
import { ServiceException } from '../common/excpetion';

export class PageService extends BaseService {
    async GetLoginPage(orgId: string) {
        let ctx = new ApiDataContext();
        let list = await ctx.OrgPageItem
            .Join(ctx.Page).On((m, f) => m.pageId == f.id)
            .Where(x => x.orgId == $args1, { $args1: orgId })
            .Where<Page>(x => x.type == $args1, { $args1: PageType.LoginPage }, ctx.Page)
            .ToList();

        for (let item of list) {
            item.page = await ctx.Page.First(x => x.id == $args1, { $args1: item.pageId });
        }

        return list;

    }
    CreateOrgPageItem(entity: OrgPageItem, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            let d = new OrgPageItem();
            d.ConverToEntity(entity);

            return ctx.Create(d);
        });
    }
    GetPageTmpItemsByPageId(id: string): PageTmpItem[] | PromiseLike<PageTmpItem[]> {
        let ctx = new ApiDataContext();
        return ctx.PageTmpItem.Where(x => x.pageId == $args1, { $args1: id }).OrderBy(x => x.index).ToList();
    }
    CreatePage(entity: Page, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            // let hasName = await ctx.Page.Where(x => x.name == $args1, { $args1: entity.name })
            if (!entity.name) {
                throw new ServiceException('页面名称不能为空！');
            }
            let d = new Page();
            d.ConverToEntity(entity);
            d.createTime = Date.now();
            d.viewId = Date.now() + '';
            return ctx.Create(d);
        });
    }
    UpdatePage(entity: Page, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            if (!entity.name) {
                throw new ServiceException('页面名称不能为空！');
            }
            let d = new Page();
            d.ConverToEntity(entity);
            d.updateTime = Date.now();
            return ctx.Update(d);
        });
    }
    async GetPageById(id: string) {
        let ctx = new ApiDataContext();
        return ctx.Page.First(x => x.id == $args1, { $args1: id });

    }
    async QueryPage(params: PageQueryParams) {
        let q1 = this.GetQueryPageCtx(params);
        let q2 = this.GetQueryPageCtx(params);
        if (params.countOfPage && params.pageIndex) {
            q2 = q2.Take(params.countOfPage).Skip(params.pageIndex - 1) as IQueryObject<Page>;
            return {
                list: await q2.ToList(),
                total: await q1.Count()
            }
        }
        else {
            return q1.ToList()
        }
    }

    private GetQueryPageCtx(params: PageQueryParams) {
        let ctx = new ApiDataContext();
        let q = ctx.Page as IQueryObject<Page>;
        if (params) {
            if (params.name) {
                q = q.Where(x => x.name.indexOf($args1), { $args1: params.name });
            }
            if (params.viewId) {
                q = q.Where(x => x.viewId == $args1, { $args1: params.viewId });
            }
            if (params.pageIds) {
                q = q.Contains(x => x.id, params.pageIds) as IQueryObject<Page>;
                if (params.flowNodeId) {
                    q = q.Where(x => x.flowNodeId == $args1, { $args1: params.flowNodeId });
                }
            }
            if (params.flowNodeId) {
                q = q.Where(x => x.flowNodeId == $args1, { $args1: params.flowNodeId });
            }
            if (params.orgId) {
                q = q.Join(ctx.OrgPageItem).On((m, f) => m.id == f.pageId);
                q = q.Where<OrgPageItem>(x => x.orgId == $args1, { $args1: params.orgId }, ctx.OrgPageItem);
            }
            if (params.type) {
                q = q.Where(x => x.type == $args1, { $args1: params.type });
            }
        }

        return q;
    }

    DeletePageByNodeId(nodeId: string, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            return ctx.Delete<Page>(x => x.flowNodeId == $args1, ctx.Page, {
                $args1: nodeId
            });
        });
    }

    DeletePageById(id: string, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            return ctx.Delete<Page>(x => x.id == $args1, ctx.Page, {
                $args1: id
            });
        });
    }

    CreatePageTmpItem(entity: PageTmpItem, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            let d = new PageTmpItem();
            d.ConverToEntity(entity);
            return ctx.Create(d);
        });
    }
    CreatePageTmpItems(datas: PageTmpItem[], ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            return ctx.CreateBatch(datas.map(x => new PageTmpItem().ConverToEntity<PageTmpItem>(x)));
        });
    }
    DeletePageTmpItemByPageId(pageId: string, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            return ctx.Delete<PageTmpItem>(x => x.pageId == $args1, ctx.PageTmpItem, {
                $args1: pageId
            });
        });
    }

}

export interface PageQueryParams extends QueryParamsBase {
    name?: string;
    viewId?: string;
    pageIds?: string[];
    flowNodeId?: string;
    orgId?: string;
    type?: string;
}